package cn.wu.demo.serialport.util;

import gnu.io.SerialPort;

/**
 * Modbus工具类
 * @author wusq
 * @date 2024/1/7
 */
public class ModbusUtils {

    /**
     * @param slaveAddress 从站地址
     * @param functionCode 功能码
     * @param startAddress 起始寄存器地址
     * @param registerCount 寄存器数量
     * @return Modbus-RTU 协议请求报文
     */
    public static byte[] buildModbusRTURequest(int slaveAddress, int functionCode, int startAddress, int registerCount) {
        // 创建一个字节数组用于存储报文
        byte[] request = new byte[8];

        // 设置从机地址
        request[0] = (byte) slaveAddress;

        // 设置功能码
        request[1] = (byte) functionCode;

        // 设置起始寄存器地址（高位和低位）
        request[2] = (byte) (startAddress >> 8);
        request[3] = (byte) (startAddress & 0xFF);

        // 设置寄存器数量（高位和低位）
        request[4] = (byte) (registerCount >> 8);
        request[5] = (byte) (registerCount & 0xFF);

        // 计算CRC校验并设置到报文中
        int crc = calculateCRC(request, 6);
        request[6] = (byte) (crc & 0xFF); // 低位
        request[7] = (byte) (crc >> 8); // 高位

        return request;
    }

    private static int calculateCRC(byte[] message, int length) {
        int crc = 0xFFFF;
        for (int i = 0; i < length; i++) {
            crc ^= (message[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                if ((crc & 1) == 1) {
                    crc = (crc >> 1) ^ 0xA001;
                } else {
                    crc = crc >> 1;
                }
            }
        }
        return crc;
    }

}